<?php

declare(strict_types=1);

namespace Tools\Net;

/**
 * Class HTTPS
 * PHP version > 8 : mixed
 *
 * @package Tools\Net
 */
class HTTPS
{
    /**
     * @var array Curl options.
     *
     * @static
     */
    public static array $options = [];

    /**
     * @var array Http header options.
     *
     * @static
     */
    public static array $headers= [];

    /**
     * @var null Curl resource.
     *
     * @static
     */
    public static $curl = null;

    /**
     * Initialize HTTPS.
     *
     * @param array $options
     * @param array $headers
     *
     * @static
     */
    public static function initCurl(array $options = [], array $headers = []) : void
    {
        self::$curl = curl_init();

        self::$options = $options;
        self::$headers = $headers;
    }

    /**
     * Clean current.
     */
    public static function clean() : void
    {
        if (is_null(self::$curl)) curl_close(self::$curl);

        self::$options = [];
        self::$headers = [];
    }

    /**
     * Restful interface implementation.
     *
     * @param string $url
     * @param array $data
     * @param string $type = 'GET'
     *
     * @static
     *
     * @return string|bool
     */
    public static function sendRequest(string $url, array $data = [], string $type = 'GET') : mixed
    {
        $result = false;

        switch ($type) {
            case 'GET':
                $result = self::curlGet($url);
                break;
            case 'POST':
                $result = self::curlPost($url, $data);
                break;
            case 'PUT':
                $result = self::curlPut($url, $data);
                break;
            case 'DELETE':
                $result = self::curlDelete($url, $data);
                break;
            case 'PATCH':
                $result = self::curlPatch($url, $data);
                break;
            default:
                // handle
                // $result = self::defaultResult();
                break;
        }

        return $result;
    }

    /**
     * Support HTTPS(avoid).
     *
     * @param string $url
     *
     * @static
     *
     * @return string|bool
     */
    protected static function curlGet(string $url) : mixed
    {
        $header = [
            'Content-type:app/json;',
            'Accept:app/json',
        ];
        array_push(self::$headers, ...$header);


        self::avoidSSLAndHostsCheck(self::$curl);

        curl_setopt(self::$curl, CURLOPT_URL, $url);
        curl_setopt(self::$curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt(self::$curl, CURLOPT_HTTPHEADER, self::$headers);
        curl_setopt(self::$curl, CURLINFO_HEADER_OUT, TRUE);

        self::setOptions();

        $output = curl_exec(self::$curl);

        curl_close(self::$curl);

        return $output;
    }

    /**
     * Support HTTPS(avoid).
     *
     * @param string $url
     * @param array $data
     *
     * @static
     *
     * @return string|bool
     */
    protected static function curlPost(string $url, array $data) : mixed
    {
        $data = json_encode($data);

        $header = [
            'Content-type:app/json;charset="utf-8"',
            'Accept:app/json',
        ];
        array_push(self::$headers, ...$header);

        self::avoidSSLAndHostsCheck(self::$curl);

        curl_setopt(self::$curl, CURLOPT_URL, $url);
        curl_setopt(self::$curl, CURLOPT_POST, true);
        curl_setopt(self::$curl, CURLOPT_POSTFIELDS, $data);
        curl_setopt(self::$curl, CURLOPT_HTTPHEADER, self::$headers);
        curl_setopt(self::$curl, CURLOPT_RETURNTRANSFER, true);

        self::setOptions();

        $output = curl_exec(self::$curl);

        curl_close(self::$curl);

        return $output;
    }

    /**
     * @param string $url
     * @param array $data
     *
     * @static
     *
     * @return string|bool
     */
    protected static function curlPut(string $url, array $data) : mixed
    {
        $data = json_encode($data);

        self::$headers[] = 'Content-type:app/json';

        self::avoidSSLAndHostsCheck(self::$curl);

        curl_setopt(self::$curl, CURLOPT_URL, $url);
        curl_setopt(self::$curl, CURLOPT_HTTPHEADER, self::$headers);
        curl_setopt(self::$curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt(self::$curl, CURLOPT_CUSTOMREQUEST, "PUT");
        curl_setopt(self::$curl, CURLOPT_POSTFIELDS, $data);

        self::setOptions();

        $output = curl_exec(self::$curl);

        curl_close(self::$curl);

        return $output;
    }

    /**
     * @param string $url
     * @param array $data
     *
     * @static
     *
     * @return string|bool
     */
    protected static function curlDelete(string $url, array $data) : mixed
    {
        $data = json_encode($data);

        self::$headers[] = 'Content-type:app/json';

        self::avoidSSLAndHostsCheck(self::$curl);

        curl_setopt(self::$curl, CURLOPT_URL, $url);
        curl_setopt(self::$curl, CURLOPT_HTTPHEADER, self::$headers);
        curl_setopt(self::$curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt(self::$curl, CURLOPT_CUSTOMREQUEST, "DELETE");
        curl_setopt(self::$curl, CURLOPT_POSTFIELDS, $data);

        self::setOptions();

        $output = curl_exec(self::$curl);

        curl_close(self::$curl);

        return $output;
    }

    /**
     * @param string $url
     * @param array $data
     *
     * @static
     *
     * @return string|bool
     */
    protected static function curlPatch(string $url, array $data) : mixed
    {
        $data = json_encode($data);

        self::$headers[] = 'Content-type:app/json';

        self::avoidSSLAndHostsCheck(self::$curl);

        curl_setopt(self::$curl, CURLOPT_URL, $url);
        curl_setopt(self::$curl, CURLOPT_HTTPHEADER, self::$headers);
        curl_setopt(self::$curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt(self::$curl, CURLOPT_CUSTOMREQUEST, "PATCH");
        curl_setopt(self::$curl, CURLOPT_POSTFIELDS, $data);

        self::setOptions();

        $output = curl_exec(self::$curl);

        curl_close(self::$curl);

        return $output;
    }

    /**
     * Set curl options.
     *
     * @static
     */
    protected static function setOptions() : void
    {
        if (! empty(self::$options)) {
            foreach (self::$options as $key => $value) {
                curl_setopt(self::$curl, $key, $value);
            }
        }
    }

    /**
     * @param $curl
     *
     * @static
     */
    protected static function avoidSSLAndHostsCheck($curl) : void
    {
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
    }

    /**
     * Set the default return value.
     *
     * @static
     *
     * @return mixed
     */
    protected static function defaultResult() : mixed
    {
        return false;
    }
}
